<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能调度模型 - 哈尔滨智慧公交</title>
    <link rel="stylesheet" href="css/style.css">
    <script src="js/echarts.min.js"></script>
</head>

<body>
    <div class="navbar">
        <a href="index.html">首页</a>
        <a href="traffic_trend.html">客流趋势分析</a>
        <a href="station_ranking.html">站点客流排行</a>
        <a href="funnel_analysis.html">线路站点客流分析</a>
        <a href="line_comparison.html">线路客流量对比</a>
        <a href="transfer_heatmap.html">换乘热度分析</a>
        <a href="poi_analysis.html">站点周边客流特征</a>
        <a href="anomaly_detection.html">异常客流检测</a>
        <a href="od_analysis.html">路径OD分析</a>
        <a href="stop_frequency_usage_analysis.html">站停频率分析</a>
        <a href="dispatch_suggestion.html">智能调度模型</a>
    </div>

    <div class="page-container">
        <div class="chart-header">
            <h2 class="chart-title">智能调度模型</h2>
            <p class="chart-description">
                本页面默认展示线路1的数据。您可以通过筛选查询特定线路、站点或小时的数据，为公交和地铁的运力调配提供数据支持，旨在提升运营效率和乘客体验。
            </p>
            <div class="filters">
                <select id="routeIdFilter"></select>
                <select id="stationIdFilter"></select>
                <select id="hourFilter"></select>
                <button id="filterBtn">查询</button>
            </div>
        </div>

        <div id="dispatch-chart" class="chart-container"></div>

        <div class="table-container">
            <div class="table-header">
                <h3>调度数据详情</h3>
                <button id="reset-table-filter" style="display:none;">显示全部</button>
            </div>
            <table id="suggestion-table">
                <thead>
                    <tr>
                        <th>线路ID</th>
                        <th>站点ID</th>
                        <th>小时</th>
                        <th>上车人数</th>
                        <th>平均拥挤度</th>
                    </tr>
                </thead>
                <tbody>
                    <!-- Data will be inserted here by JavaScript -->
                </tbody>
            </table>
            <div id="table-pagination">
                <!-- Pagination controls will be inserted here -->
            </div>
        </div>
    </div>

    <div id="main" style="width: 100%; height: 800px;"></div>
    <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', async function () {
            const filterBtn = document.getElementById('filterBtn');
            const routeIdFilter = document.getElementById('routeIdFilter');
            const stationIdFilter = document.getElementById('stationIdFilter');
            const hourFilter = document.getElementById('hourFilter');
            const tableBody = document.querySelector('#suggestion-table tbody');
            const dispatchChart = echarts.init(document.getElementById('dispatch-chart'));
            const resetTableFilterBtn = document.getElementById('reset-table-filter');

            let fullData = [];
            let tableData = [];
            let currentPage = 1;
            const rowsPerPage = 15;
            let selectedHour = null;

            async function populateFilters() {
                // Populate Hour Filter
                hourFilter.innerHTML = '<option value="">所有时间</option>';
                for (let i = 0; i < 24; i++) {
                    hourFilter.innerHTML += `<option value="${i}">${i}:00 - ${i}:59</option>`;
                }

                // Populate Route Filter
                try {
                    const response = await fetch('/api/dispatch/routes');
                    const routes = await response.json();
                    routeIdFilter.innerHTML = '<option value="">所有线路</option>';
                    routes.forEach(routeId => {
                        routeIdFilter.innerHTML += `<option value="${routeId}">${routeId}</option>`;
                    });
                } catch (error) {
                    console.error('Failed to load routes:', error);
                    routeIdFilter.innerHTML = '<option value="">无法加载线路</option>';
                }

                // Initial state for station filter
                stationIdFilter.innerHTML = '<option value="">所有站点</option>';
                stationIdFilter.disabled = true;
            }

            routeIdFilter.addEventListener('change', async function () {
                const selectedRouteId = this.value;
                stationIdFilter.innerHTML = '<option value="">所有站点</option>';
                if (selectedRouteId) {
                    stationIdFilter.disabled = false;
                    try {
                        const response = await fetch(`/api/dispatch/stations?routeId=${selectedRouteId}`);
                        const stations = await response.json();
                        stations.forEach(stationId => {
                            stationIdFilter.innerHTML += `<option value="${stationId}">${stationId}</option>`;
                        });
                    } catch (error) {
                        console.error('Failed to load stations:', error);
                        stationIdFilter.innerHTML = '<option value="">无法加载站点</option>';
                    }
                } else {
                    stationIdFilter.disabled = true;
                }
            });

            async function fetchData(isInitialLoad = false) {
                let routeId = routeIdFilter.value;
                const stationId = stationIdFilter.value;
                const hour = hourFilter.value;

                let url = '/api/dispatch/suggestion_data';
                const params = new URLSearchParams();

                if (isInitialLoad && !routeId && !stationId && !hour) {
                    routeId = '1';
                    routeIdFilter.value = '1';
                    await new Promise(resolve => setTimeout(resolve, 0));
                    await routeIdFilter.dispatchEvent(new Event('change'));
                }

                if (routeId) params.append('routeId', routeId);
                if (stationId) params.append('stationId', stationId);
                if (hour) params.append('hour', hour);

                if (params.toString()) {
                    url += `?${params.toString()}`;
                }

                try {
                    const response = await fetch(url);
                    if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
                    fullData = await response.json();

                    if (Array.isArray(fullData)) {
                        fullData.sort((a, b) => {
                            if (a.hour !== b.hour) return a.hour - b.hour;
                            return String(a.stationId).localeCompare(String(b.stationId));
                        });
                    }

                    selectedHour = null;
                    currentPage = 1;
                    updateDisplay();
                    renderChart(fullData);

                } catch (error) {
                    console.error('获取调度建议数据失败:', error);
                    tableBody.innerHTML = `<tr><td colspan="5">数据加载失败，请检查后端服务是否正常。</td></tr>`;
                    fullData = [];
                    updateDisplay();
                }
            }

            function updateDisplay() {
                if (selectedHour !== null) {
                    tableData = fullData.filter(item => item.hour === selectedHour);
                    resetTableFilterBtn.style.display = 'inline-block';
                } else {
                    tableData = fullData;
                    resetTableFilterBtn.style.display = 'none';
                }
                renderTable();
                renderPagination();
            }

            function renderTable() {
                tableBody.innerHTML = '';
                if (!tableData || tableData.length === 0) {
                    tableBody.innerHTML = '<tr><td colspan="5">未找到符合条件的数据。</td></tr>';
                    return;
                }

                const startIndex = (currentPage - 1) * rowsPerPage;
                const endIndex = startIndex + rowsPerPage;
                const paginatedData = tableData.slice(startIndex, endIndex);

                paginatedData.forEach(item => {
                    const row = `<tr>
                        <td>${item.routeId}</td>
                        <td>${item.stationId}</td>
                        <td>${item.hour}</td>
                        <td>${item.onboard}</td>
                        <td>${item.avgCrowdLevel != null ? item.avgCrowdLevel.toFixed(2) : 'N/A'}</td>
                    </tr>`;
                    tableBody.innerHTML += row;
                });
            }

            function renderPagination() {
                const paginationContainer = document.getElementById('table-pagination');
                paginationContainer.innerHTML = '';
                const pageCount = Math.ceil(tableData.length / rowsPerPage);

                if (pageCount <= 1) return;

                let paginationHTML = '';

                // First page button
                paginationHTML += `<button class="pagination-btn" onclick="changePage(1)" ${currentPage === 1 ? 'disabled' : ''}>首页</button>`;

                // Previous button
                paginationHTML += `<button class="pagination-btn" onclick="changePage(${currentPage - 1})" ${currentPage === 1 ? 'disabled' : ''}>上一页</button>`;

                // Page info
                paginationHTML += `<span> Page ${currentPage} of ${pageCount} </span>`;

                // Next button
                paginationHTML += `<button class="pagination-btn" onclick="changePage(${currentPage + 1})" ${currentPage === pageCount ? 'disabled' : ''}>下一页</button>`;

                // Last page button
                paginationHTML += `<button class="pagination-btn" onclick="changePage(${pageCount})" ${currentPage === pageCount ? 'disabled' : ''}>末页</button>`;

                paginationContainer.innerHTML = paginationHTML;
            }

            window.changePage = function (page) {
                const pageCount = Math.ceil(tableData.length / rowsPerPage);
                if (page < 1 || page > pageCount) return;
                currentPage = page;
                renderTable();
                renderPagination();
            }

            function renderChart(data) {
                if (!data || data.length === 0) {
                    dispatchChart.clear();
                    dispatchChart.setOption({
                        title: {
                            text: '没有可供分析的数据',
                            subtext: '请调整筛选条件后重试',
                            left: 'center',
                            top: 'center'
                        }
                    });
                    return;
                }

                const chartDataByHour = Array(24).fill(0).map(() => ({ onboardSum: 0, crowdSum: 0, count: 0 }));
                data.forEach(item => {
                    chartDataByHour[item.hour].onboardSum += item.onboard;
                    chartDataByHour[item.hour].crowdSum += item.avgCrowdLevel;
                    chartDataByHour[item.hour].count++;
                });

                const hours = Array.from({ length: 24 }, (_, i) => `${i}:00`);
                const avgOnboard = chartDataByHour.map(h => h.count > 0 ? h.onboardSum / h.count : 0);
                const avgCrowd = chartDataByHour.map(h => h.count > 0 ? h.crowdSum / h.count : 0);

                var option = {
                    title: {
                        text: '平均上车人数与拥挤度趋势'
                    },
                    tooltip: {
                        trigger: 'axis',
                        formatter: function (params) {
                            let res = params[0].name;
                            params.forEach(param => {
                                res += `<br/>${param.marker} ${param.seriesName}: ${param.value != null ? param.value.toFixed(2) : 'N/A'}`;
                            });
                            return res;
                        }
                    },
                    legend: {
                        data: ['平均上车人数', '平均拥挤度'],
                        bottom: 10
                    },
                    grid: {
                        left: '3%',
                        right: '4%',
                        bottom: '15%',
                        containLabel: true
                    },
                    xAxis: {
                        type: 'category',
                        data: hours
                    },
                    yAxis: [
                        {
                            type: 'value',
                            name: '平均上车人数',
                            axisLabel: {
                                formatter: function (value) {
                                    if (value >= 1000) {
                                        return (value / 1000) + 'k';
                                    }
                                    return value;
                                }
                            }
                        },
                        {
                            type: 'value',
                            name: '平均拥挤度',
                            axisLabel: {
                                formatter: '{value}'
                            }
                        }
                    ],
                    series: [
                        {
                            name: '平均上车人数',
                            type: 'bar',
                            data: avgOnboard,
                            yAxisIndex: 0
                        },
                        {
                            name: '平均拥挤度',
                            type: 'line',
                            yAxisIndex: 1,
                            data: avgCrowd,
                            smooth: true,
                            itemStyle: {
                                color: '#91CC75'
                            }
                        }
                    ]
                };

                dispatchChart.setOption(option, true);
            }

            dispatchChart.on('click', function (params) {
                if (params.componentType === 'series' && (params.seriesType === 'bar' || params.seriesType === 'line')) {
                    const hour = parseInt(params.name, 10);
                    selectedHour = hour;
                    currentPage = 1;
                    updateDisplay();
                }
            });

            resetTableFilterBtn.addEventListener('click', function () {
                selectedHour = null;
                currentPage = 1;
                updateDisplay();
            });

            await populateFilters();
            await fetchData(true); // Initial data load for route 1
            filterBtn.addEventListener('click', () => fetchData());
        });
    </script>
    <script src="js/common.js"></script>
</body>

</html>